<?php
/**
 * Pert Library
 * Tree View Classes
 *
 * @author	Emre Hasegeli <hasegeli@gmail.com>
 * @license	GNU General Public License v3
 */

namespace Pert;

class TreeLeaf
{
	protected $name;

	protected $properties = array();

	protected $parent;

	public function __construct($name, $property = NULL)
	{
		$this->name = new TreeName($name);

		if($property)
			$this->properties[0] = $property;
	}

	public function __toString()
	{
		$html = '
<table border="0" cellspacing="0" cellpadding="0" >
	<tr >
		<td valign="top" >
			<img class="tree_collapseicon" src="buttons/leaf.png" />
		</td>
		<td >
			<table border="0" cellspacing="0" cellpadding="0" >
				<tr >
					<td >';

		$html .= '
						<div class="tree_';

		if($this->properties)
			$html .= 'leafname';
		else
			$html .= 'leafproperty';

		$html .= '" >
							' . $this->name . '
						</div>';

		$html .= '
					</td>';

		foreach($this->properties as $part)
				$html .= '
					<td >
						<div class="tree_leafproperty" >
							' . $part . '
						</div>
					</td>';

		$html .= '
				</tr>
			</table>
		</td>
	</tr>
</table>';

		return $html;
	}

	public function AddProperty($property)
	{
		$this->properties[] = $property;
	}

	public function AddLink($href, $target = NULL)
	{
		if(empty($this->link))
			$this->name->AddLink($href . $this->parametersToHref(), $target);
		else
			throw new Exception('There can be only one one link');
	}

	public function Parent()
	{
		return $this->parent;
	}

	public function Colour($color)
	{
		$this->name->Colour($color);
	}

	protected $parameters = array();

	protected function parametersToHref()
	{
		if(($this->parent->parameters) OR ($this->parameters))
		{
			$count = 0;

			$href = '?';

			foreach($this->parent->parameters AS $parameter => $value)
				if(empty($this->parameters[$parameter]))
				{
					if($count++)
						$href .= '&';

					$href .= $parameter . '=' . $value;
				}

			foreach($this->parameters AS $parameter => $value)
			{
				if($count++)
					$href .= '&';

				$href .= $parameter . '=' . $value;
			}

			return $href;
		}
	}

	public function AddParameter($parameter, $value)
	{
		$this->parameters[$parameter] = $value;
	}

	public function Parameter($parameter)
	{
		if(isset($this->parameters[$parameter]))
			return $this->parameters[$parameter];

		if(isset($this->parent->parameters[$parameter]))
			return $this->parent->parameters[$parameter];
	}
}

class TreeBranchlet extends TreeLeaf
{
	protected $id;

	protected $buttons = array();

	protected $links = array();

	protected $leaves = array();

	protected $branches = array();

	protected $collapsed = false;

	protected static $staticid = 0;

	public function __construct($name, $property = NULL)
	{
		parent::__construct($name, $property);

		$this->id = self::$staticid++;
	}

	public function __toString()
	{
		$html = '
<table border="0" cellspacing="0" cellpadding="0" >
	<tr >
		<td valign="top" >
			<img class="tree_collapseicon" id="img' . $this->id . '" ';

		if(($this->Among()) and ($this->collapsed))
			$html .= 'src="buttons/collapseicon.png" ';
		else
			$html .= 'src="buttons/uncollapseicon.png" ';

		if($this->Among())
			$html .= 'onclick="collapse(' . "'" . $this->id . "'" . ');" ';

		$html .= '/>
		</td>
		<td >
			<table border="0" cellspacing="0" cellpadding="0" >
				<tr >
					<td >
						<table border="0" cellspacing="0" cellpadding="0" >
							<tr >';

		foreach($this->buttons as $part)
			$html .= '
								<td >
									' . $part . '
								</td>';

		foreach($this->links as $part)
			$html .= '
								<td >
									' . $part . '
								</td>';

		$html .= '
								<td >
									<div class="tree_';

		if($this->Among())
			$html .= 'uncollapsedbranchletname';
		else
			$html .= 'collapsedbranchletname';

		$html .= '" >';


		$html .= '
										' . $this->name;

		$html .= '
									</div>
								</td>';

		foreach($this->properties as $part)
			$html .= '
								<td >
									<div class="tree_branchletproperty" >
										' . $part . '
									</div>
								</td>';
		$html .= '
							</tr>
						</table>
					</td>
				</tr>';

		if($this->Among())
		{
			$html .= '
				<tr id="tr' . $this->id . '" ';

			if($this->collapsed)
				$html .= 'style="display:none" ';

			$html .='>
					<td >
						<table border="0" cellspacing="0" cellpadding="0" >';

			foreach($this->leaves as $part)
				$html .= '
								<tr >
									<td >
										' . $part . '
									</td>
								</tr>';

			foreach($this->branches as $part)
				$html .= '
								<tr >
									<td >
										' . $part . '
									</td>
								</tr>';

			$html .= '
						</table>
					</td>
				</tr>';
		}

		$html .= '
			</table>
		</td>
	</tr>
</table>';

		return $html;
	}

	public function Add($part)
	{
		if($part instanceof TreeLeaf)
		{
			$part->parent = $this;

			if($part instanceof TreeBranchlet)
				$this->branches[] = $part;
			else
				$this->leaves[] = $part;

			return $part;
		}
		else
			throw new Exception('This object cannot be on a tree.');
	}

	public function Among()
	{
		return (($this->leaves) or ($this->branches));
	}

	public function Pressed()
	{
		if(isset($_POST[$this->id]))
			return TreeButtonKey::Back($_POST[$this->id]);
	}

	public function Collapse()
	{
		$this->collapsed = true;
	}

	public function AddButton($name)
	{
		$this->buttons[] = new TreeButton($this->id, $name);
	}

	public function AddLink($href, $target = NULL)
	{
		if(($target) or ($this->name->Linked()))
			$this->links[] = new TreeLink($href . $this->parametersToHref(), $target);
		else
			parent::AddLink($href);
	}

	protected function parametersToHref()
	{
		if($this->parameters)
		{
			$href = '?';

			$count = 0;

			foreach($this->parameters AS $parameter => $value)
			{
				if($count++)
					$href .= '&';

				$href .= $parameter . '=' . $value;
			}

			return $href;
		}
	}

	public function Parameter($parameter)
	{
		if(isset($this->parameters[$parameter]))
			return $this->parameters[$parameter];
	}
}

class TreeBranch extends TreeBranchlet
{
	public function __toString()
	{
		$html = '
<table border="0" cellspacing="0" cellpadding="0" >
	<tr >
		<td valign="top" >
			<img class="tree_collapseicon" id="img' . $this->id . '" ';

		if(($this->Among()) and ($this->collapsed))
			$html .= 'src="buttons/collapseicon.png" ';
		else
			$html .= 'src="buttons/uncollapseicon.png" ';

		if($this->Among())
			$html .= 'onclick="collapse(' . "'" . $this->id . "'" . ');" ';

		$html .= '/>
		</td>
		<td >
			<table border="0" cellspacing="0" cellpadding="0" >
				<tr >
					<td >
						<table border="0" cellspacing="0" cellpadding="0" >
							<tr >';

		foreach($this->buttons as $part)
			$html .= '
								<td >
									' . $part . '
								</td>';

		foreach($this->links as $part)
			$html .= '
								<td >
									' . $part . '
								</td>';

		$html .= '
								<td >
									<div class="tree_branchname" >';


		$html .= '
										' . $this->name;

		$html .= '
									</div>
								</td>';

		foreach($this->properties as $part)
			$html .= '
								<td >
									<div class="tree_branchproperty" >
										' . $part . '
									</div>
								</td>';
		$html .= '
							</tr>
						</table>
					</td>
				</tr>';

		if($this->Among())
		{
			$html .= '
				<tr id="tr' . $this->id . '" ';

			if($this->collapsed)
				$html .= 'style="display:none" ';

			$html .='>
					<td >
						<table border="0" cellspacing="0" cellpadding="0" >';

			foreach($this->leaves as $part)
				$html .= '
								<tr >
									<td >
										' . $part . '
									</td>
								</tr>';

			foreach($this->branches as $part)
				$html .= '
								<tr >
									<td >
										' . $part . '
									</td>
								</tr>';

			$html .= '
						</table>
					</td>
				</tr>';
		}

		$html .= '
			</table>
		</td>
	</tr>
</table>';

		return $html;
	}
}

class Tree extends TreeBranchlet
{
	public function __toString()
	{
		$html = <<<EOD
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html>
	<head>
		<title>
			{$this->name->Name()}
		</title>

		<link rel="stylesheet" type="text/css" href="tree.css" />

		<script type="text/javascript" >

function collapse(id)
{
	if(document.getElementById('tr' + id).style.display == "none")
	{
		document.getElementById('tr' + id).style.display = "block";
		document.getElementById('img' + id).src = "buttons/uncollapseicon.png";
	}
	else
	{
		document.getElementById('tr' + id).style.display = "none";
		document.getElementById('img' + id).src = "buttons/collapseicon.png";
	}
}

function InsertHTMLTag(id, hTMLTag)
{
	var textArea = document.getElementById(id);

	if(document.getSelection)
	{
		var text1 = textArea.value.substring(0, textArea.selectionStart);

		var text2 = textArea.value.substring(textArea.selectionStart, textArea.selectionEnd);

		var text3 = textArea.value.substr(textArea.selectionEnd);

		textArea.value = text1 + '<' + hTMLTag + ' >' + text2 + '</' + hTMLTag + '>' + text3;
	}
	else if(document.selection.type == 'Text')
	{
		var newRange = document.selection.createRange();

		textArea.focus();

		newRange.text = '<' + hTMLTag + ' >' + newRange.text + '</' + hTMLTag + '>';

		newRange.select();
	}
}

function InsertCharacter(id, character)
{
	var textArea = document.getElementById(id);

	if(document.getSelection)
	{
		var text1 = textArea.value.substring(0, textArea.selectionStart);

		var text2 = textArea.value.substr(textArea.selectionEnd);

		textArea.value = text1 + character + text2;
	}
	else if(document.selection.type == 'Text')
	{
		var newRange = document.selection.createRange();

		textArea.focus();

		newRange.text = character;

		newRange.select();
	}
}

function InsertTwoCharacter(id, character)
{
	var textArea = document.getElementById(id);

	if(document.getSelection)
	{
		var text1 = textArea.value.substring(0, textArea.selectionStart);

		var text2 = textArea.value.substring(textArea.selectionStart, textArea.selectionEnd);

		var text3 = textArea.value.substr(textArea.selectionEnd);

		textArea.value = text1 + character + text2 + character + text3;
	}
	else if(document.selection.type == 'Text')
	{
		var newRange = document.selection.createRange();

		textArea.focus();

		newRange.text = character + newRange.text + character;

		newRange.select();
	}
}

		</script>
	</head>

	<body>
		<form 
EOD;

	if($this->parametersToHref())
		$html .= 'action="' . $this->parametersToHref() . '" ';

		$html .= 'enctype="multipart/form-data" method="POST" >
			' . parent::__toString() . '
		</form>
	</body>
</html>';

		return $html;
	}
}

class TreeName
{
	private $name;

	private $href;

	private $target;

	private $color;

	public function __construct($name)
	{
		$this->name = $name;
	}

	public function AddLink($href, $target = NULL)
	{
		$this->href = $href;

		$this->target = $target;
	}

	public function Colour($color)
	{
		$this->color = $color;
	}

	public function __toString()
	{
		$tag = explode('<', $this->name);

		$html = '
<a ';

		if(empty($tag[1]))
			$html .= 'name="' . $this->name . '" ';

		if(isset($this->href))
		{
			$html .= 'href="' . $this->href . '" ';

			if($this->target)
				$html .= 'target="' . $this->target . '" ';
		}

		$html .= '>';

		if($this->color)
			$html .= '
	<font color="' . $this->color . '" >' . $this->name . '</font>';

		else
			$html .= '
	' . $this->name;

		$html .= '
</a>';

		return $html;
	}

	public function Linked()
	{
		return isset($this->href);
	}

	public function Name()
	{
		return $this->name;
	}
}

class TreeButton
{
	private $name;

	private $value;

	public function __construct($name, $value)
	{
		$this->name = $name;

		$this->value = $value;
	}

	public function __toString()
	{
		$insideButton = new TreeButtonKey($this->value);

		return '
<button class="tree_button" type="submit" id="' . $this->value . '" name="' . $this->name . '" value="' . $this->value . '" >
	' . $insideButton .'
</button>';
	}
}

class TreeLink
{
	private $href;

	private $target;

	public function __construct($href, $target = NULL)
	{
		$this->href = $href;

		$this->target = $target;
	}

	public function __toString()
	{
		$insideButton = new TreeButtonKey('link');

		$html = '
<a href="' . $this->href . '" ';

		if($this->target)
			$html .= 'target="' . $this->target . '" ';

		$html .= '>
	' . $insideButton . '
</a>';

		return $html;
	}
}

class TreeButtonKey
{
	private $name;

	public function __construct($name)
	{
		$this->name = $name;
	}

	public function __toString()
	{
		$name = explode('_', $this->name);

		$id = 0;
		while(isset($name[++$id]));
		--$id;

		if(file_exists('buttons/' . $name[$id] . '.png'))
			return '<img src="buttons/' . $name[$id] . '.png" alt="' . $name[$id] .'" title="' . $this->name .'" border="0" />';
		else
			return $this->name;
	}

	public static function Back($name)
	{
		$name = explode('<IMG', $name);

		if(!isset($name[1]))
			$name = explode('<img', $name[0]);

		if(isset($name[1]))
		{
			$name = explode('title=', $name[1]);

			$name = explode(' ', $name[1]);

			$name = explode('"', $name[0]);

			if(isset($name[1]))
				$name[0] = $name[1];
		}

		return $name[0];
	}
}
